################################################################################
# Imports
################################################################################

import Education
import urlparse
import re
import pprint #TODO: Remove me
import EducationGroup
from EducationGUIHelper import *
import ycp
ycp.import_module("SCR")
from ycp import SCR, Path

################################################################################
# Constants
################################################################################

MIN_TOLERANCE = 0
MAX_TOLERANCE = 300
HOSTNAME_REGEX = "^((([a-zA-Z0-9][a-zA-Z0-9-]*\.)+[a-zA-Z]{2,})|([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}))(:[0-9]+)?$"
EXTENSION_REGEX = "^.?[a-zA-Z0-9+-]+$"
WHITELIST_MODE_DEFAULT = 'normal'

################################################################################
# Presets
################################################################################
                    
filter_presets =  {
                    'High' :  {
                                'tolerance': 40,
                                'banned_topics': [
                                                    'Chat',
                                                    'Conspiracy',
                                                    'Domains for sale',
                                                    'Drug advocacy',
                                                    'Forums',
                                                    'Gambling',
                                                    #'Games',
                                                    'Gore',
                                                    'Identity theft',
                                                    'Illegal drugs',
                                                    'Legal drugs',
                                                    'Malware',
                                                    #'Music',
                                                    #'News',
                                                    'Nudism',
                                                    'Peer to peer',
                                                    'Personals',
                                                    'Pornography',
                                                    'Profanity',
                                                    'Proxies',
                                                    'Racism / intolerance',
                                                    'Secret societies',
                                                    #'Sports',
                                                    #'Translation',
                                                    #'Travel',
                                                    'Violence',
                                                    'Warez / hacking',
                                                    'Weapons',
                                                    'Webmail'
                                                  ]
                              },
                    'Moderate' :  {
                                    'tolerance': 80,
                                    'banned_topics': [
                                                        #'Chat',
                                                        'Conspiracy',
                                                        'Domains for sale',
                                                        'Drug advocacy',
                                                        #'Forums',
                                                        'Gambling',
                                                        #'Games',
                                                        'Gore',
                                                        'Identity theft',
                                                        'Illegal drugs',
                                                        'Legal drugs',
                                                        'Malware',
                                                        #'Music',
                                                        #'News',
                                                        'Nudism',
                                                        'Peer to peer',
                                                        'Personals',
                                                        'Pornography',
                                                        'Profanity',
                                                        'Proxies',
                                                        'Racism / intolerance',
                                                        #'Secret societies',
                                                        #'Sports',
                                                        #'Translation',
                                                        #'Travel',
                                                        'Violence',
                                                        'Warez / hacking',
                                                        'Weapons',
                                                        #'Webmail'
                                                      ]
                                  },
                    'Low' :  {
                                'tolerance': 120,
                                'banned_topics': [
                                                    #'Chat',
                                                    #'Conspiracy',
                                                    #'Domains for sale',
                                                    #'Drug advocacy',
                                                    #'Forums',
                                                    'Gambling',
                                                    #'Games',
                                                    'Gore',
                                                    'Identity theft',
                                                    'Illegal drugs',
                                                    #'Legal drugs',
                                                    'Malware',
                                                    #'Music',
                                                    #'News',
                                                    'Nudism',
                                                    #'Peer to peer',
                                                    #'Personals',
                                                    'Pornography',
                                                    'Profanity',
                                                    #'Proxies',
                                                    'Racism / intolerance',
                                                    #'Secret societies',
                                                    #'Sports',
                                                    #'Translation',
                                                    #'Travel',
                                                    #'Violence',
                                                    'Warez / hacking',
                                                    'Weapons',
                                                    #'Webmail'
                                                  ]
                              },
                    'Minimal' :  {
                                    'tolerance': 160,
                                    'banned_topics': [
                                                        #'Chat',
                                                        #'Conspiracy',
                                                        #'Domains for sale',
                                                        #'Drug advocacy',
                                                        #'Forums',
                                                        #'Gambling',
                                                        #'Games',
                                                        #'Gore',
                                                        'Identity theft',
                                                        'Illegal drugs',
                                                        #'Legal drugs',
                                                        'Malware',
                                                        #'Music',
                                                        #'News',
                                                        'Nudism',
                                                        #'Peer to peer',
                                                        #'Personals',
                                                        'Pornography',
                                                        #'Profanity',
                                                        #'Proxies',
                                                        'Racism / intolerance',
                                                        #'Secret societies',
                                                        #'Sports',
                                                        #'Translation',
                                                        #'Travel',
                                                        #'Violence',
                                                        #'Warez / hacking',
                                                        #'Weapons',
                                                        #'Webmail'
                                                      ]
                                  }                      
                  }

filter_categories = [
                      'Chat', 'Conspiracy', 'Domains for sale', 'Drug advocacy', 'Forums',
                      'Gambling', 'Games', 'Gore', 'Identity theft', 'Illegal drugs',
                      'Legal drugs', 'Malware', 'Music', 'News', 'Nudism', 'Peer to peer',
                      'Personals', 'Pornography', 'Profanity', 'Proxies', 'Racism / intolerance',
                      'Secret societies', 'Sports', 'Translation', 'Travel', 'Violence',
                      'Warez / hacking', 'Weapons', 'Webmail'
                    ]

valid_whitelist_modes = ['normal', 'only']

################################################################################
# Functions
################################################################################

class EducationFilter:

  def __init__(self):

    self.enabled = False
    self.tolerance = filter_presets['High']['tolerance']
    self.banned_topics = list(filter_presets['High']['banned_topics'])
    self.whitelist = []
    self.whitelist_mode = WHITELIST_MODE_DEFAULT
    self.blacklist = []
    self.banned_keywords = []
    self.banned_extensions = []
    self.modified = False

  def set_enabled(self, enabled, loading=False):
    self.modified |= (enabled != self.enabled) and not loading
    self.enabled = enabled

  def set_tolerance(self, tolerance, loading=False):
    self.modified |= (tolerance != self.tolerance) and not loading
    self.tolerance = tolerance

  def add_banned_topic(self, topic, loading=False):
    if (not topic in self.banned_topics) and (topic in filter_categories):
      self.modified |= not loading
      self.banned_topics.append(topic)
      self.banned_topics.sort()

  def remove_banned_topic(self, topic, loading=False):    
    if (topic in self.banned_topics):
      self.modified |= not loading
      self.banned_topics.remove(topic)
      self.banned_topics.sort()

  def add_whitelist_site(self, site, loading=False):
    if (not site in self.whitelist):
      self.modified |= not loading
      self.whitelist.append(site)

  def remove_whitelist_site(self, site, loading=False):
    if (site in self.whitelist):
      self.modified |= not loading
      self.whitelist.remove(site)

  def set_whitelist_mode(self, mode, loading=False):
    self.modified |= (mode != self.whitelist_mode) and not loading
    self.whitelist_mode = mode

  def add_blacklist_site(self, site, loading=False):
    if (not site in self.blacklist):
      self.modified |= not loading
      self.blacklist.append(site)

  def remove_blacklist_site(self, site, loading=False):
    if (site in self.blacklist):
      self.modified |= not loading
      self.blacklist.remove(site)

  def add_banned_keyword(self, keyword, loading=False):
    if (not keyword in self.banned_keywords):
      self.modified |= not loading
      self.banned_keywords.append(keyword)

  def remove_banned_keyword(self, keyword, loading=False):
    if (keyword in self.banned_keywords):
      self.modified |= not loading
      self.banned_keywords.remove(keyword)

  def add_banned_extension(self, extension, loading=False):
    if (not extension in self.banned_extensions) and (re.match(EXTENSION_REGEX, extension)):
      ext = re.sub("^\.","", extension)
      self.modified |= not loading
      self.banned_extensions.append(ext)

  def remove_banned_extension(self, extension, loading=False):
    if (extension in self.banned_extensions) and (re.match(EXTENSION_REGEX, extension)):
      ext = re.sub("^\.","", extension)
      self.modified |= not loading
      self.banned_extensions.remove(ext)

  def save_state(self):
    
    self.undo_state = {}

    self.undo_state['enabled'] = self.enabled
    self.undo_state['tolerance'] = self.tolerance
    self.undo_state['banned_topics'] = self.banned_topics
    self.undo_state['whitelist'] = list(self.whitelist)
    self.undo_state['whitelist_mode'] = self.whitelist_mode
    self.undo_state['blacklist'] = list(self.blacklist)
    self.undo_state['banned_keywords'] = list(self.banned_keywords)
    self.undo_state['banned_extensions'] = list(self.banned_extensions)
    self.undo_state['modified'] = self.modified

  def restore_state(self):

    if (self.undo_state == None):
      return

    self.enabled = self.undo_state['enabled']
    self.tolerance = self.undo_state['tolerance']
    self.banned_topics = self.undo_state['banned_topics']
    self.whitelist = list(self.undo_state['whitelist'])
    self.whitelist_mode = self.undo_state['whitelist_mode']
    self.blacklist = list(self.undo_state['blacklist'])
    self.banned_keywords = list(self.undo_state['banned_keywords'])
    self.banned_extensions = list(self.undo_state['banned_extensions'])
    self.modified = self.undo_state['modified']

    self.undo_state = None

  def write_to_disk(self, group_name):

    path = ".edugroup.value." + group_name

    SCR.Write(Path(path + ".FILTERING_ENABLED"), self.enabled and "yes" or "no")
    SCR.Write(Path(path + ".FILTER_TOLERANCE"), self.tolerance)
    SCR.Write(Path(path + ".FILTER_TOPICS"), ",".join(self.banned_topics))
    SCR.Write(Path(path + ".FILTER_WHITELIST"), ",".join(self.whitelist))
    SCR.Write(Path(path + ".FILTER_WHITELIST_MODE"), self.whitelist_mode)
    SCR.Write(Path(path + ".FILTER_BLACKLIST"), ",".join(self.blacklist))
    SCR.Write(Path(path + ".FILTER_KEYWORDS"), ",".join(self.banned_keywords))
    SCR.Write(Path(path + ".FILTER_EXTENSIONS"), ",".join(self.banned_extensions))

    #TODO: Configure Dansguardian here


def get_filter_settings_for_group(group_name):

  return Education.get_config('groups')[group_name].filter
  
def get_group_filtering_table_data():

  filters = []

  for group_name in EducationGroup.get_education_groups():

    group = EducationGroup.load_group(group_name)
    group_name_cell = icon_cell("yast-education-filter.png", group_name)

    if group.filter.enabled:
      level = get_filter_preset_name(group.filter.tolerance, group.filter.banned_topics)
    else:
      level = "Off"

    filters.append(item(group_name, [group_name_cell, level]))

  return filters

def get_filter_categories():

  return filter_categories

def get_filter_preset_list():

  return  [ 'High', 'Moderate', 'Low', 'Minimal', 'Custom' ]

def get_filter_preset_name(tolerance, banned_topics):  
  
  for preset in filter_presets:
    if filter_presets[preset]['tolerance'] == tolerance:
      if filter_presets[preset]['banned_topics'] == banned_topics:
        return preset

  return 'Custom'

def get_filter_preset_settings(level):
  return (filter_presets[level]['tolerance'], list(filter_presets[level]['banned_topics']))

def is_valid_url(address):

  if (not re.match("^[a-zA-Z]+://", address)):
    address = "http://" + address

  try:
    parts = urlparse.urlsplit(address)
  except Exception, e:
    print e
    return False

  return ((parts.hostname) and (len(parts.hostname) > 0) and re.match(HOSTNAME_REGEX, parts.hostname))

def parse_domain(address):

  if not is_valid_url(address):
    return None

  if (not re.match("^[a-zA-Z]+://", address)):
    address = "http://" + address

  try:
    parts = urlparse.urlsplit(address)
    # Parse out the port number, if present
    return re.sub(":[0-9]+$","", parts.hostname)
  except Exception, e:
    return None

def parse_url(address):

  if not is_valid_url(address):
    return None
  else:
    # Parse out the scheme
    return re.sub("^[a-zA-Z]+://","", address)
